<?php

namespace yphp;

class Response extends Instance
{
    // 路由设置，获取
    private $route;
    // 是否执行过导出
    private $isPort = false;

    function construct()
    {
        # 当前路由
        $path = Request::instance()->path();
        $this->route = Route::instance()->findRoute(Route::routeline($path));
        return self::single();
    }

    // 地址导出
    function export()
    {
        if ($this->isPort) return;
        $this->isPort = true;
        if (!$this->route) throw new \Exception('未找到对应的路由');
        # 访问日志
        Runtime::action();
        $cache_path = self::html($this->route['path'], $this->route['args']);
        if (DealFile::cacheFile($cache_path, $this->route['cache'])) {
            $html = file_get_contents($cache_path);
        } else {
            $html = Course::instance(function () {
                return is_callable($oper = $this->route['oper']) ? call_user_func_array($oper, self::params((new \ReflectionFunction($oper))->getParameters(), $this->route['args'])) : self::analysis($oper, $this->route['args']);
            })->buffer(true);
            $this->route['cache'] > 0 && DealFile::writeFile($cache_path, $html, true);
        }
        exit(is_scalar($html) ? (string)$html : json_encode($html));
    }

    // 参数结合
    static function params($args1, $args2)
    {
        $count = count($args1) - count($args2);
        if ($count !== 1 && $count !== 0)  throw new \Exception('当前路由指向的方法参数不完整');
        if ($count === 1) {
            if (is_null($class = $args1[0]->getClass()) || $class->name !== 'yphp\Request')  throw new \Exception('当前路由的首个参数必须为Request对象');
            array_unshift($args2, Request::instance());
        }

        for ($i = $count; $i < count($args2); $i++) {
            if ($args2[$i] === '{@}') {
                if($args1[$i]->isDefaultValueAvailable()){
                    $args1[$i]->getDefaultValue();
                } else {
                    throw new \Exception('当前路由方法的' . $args1[$i] . '参数没有设置默认值');
                }
            }
        }
        return $args2;
    }

    // 解析控制器
    static function analysis($oper, $args)
    {
        preg_match_all('/^((\w+\/)*)(\w+)@(\w+)$/', $oper, $matchs);
        if(empty($matchs[0])) throw new \Exception('当前路由指向' . $oper . '不正确');
        $class = $matchs[1][0] . ucfirst($matchs[3][0]);
        $controller = Controller::load($class);
        $action = $matchs[4][0];
        if(!method_exists($controller, $action)) throw new \Exception($class . '控制器找不到' . $action . '方法');
        $ref = new \ReflectionMethod($controller, $action);
        return $ref->invokeArgs($controller, self::params($ref->getParameters(), $args));
    }


    // 获取静态文件
    static function html($path, $args)
    {
        return CACHE_ROUTE_PATH . Safe::en(Request::instance()->host()) . DS . Safe::en(serialize($path)) . DS . Safe::en(serialize($args)) . '.html';
    }

}